#include "app_message.h"
#include "log/log.h"
#include "cJSON/cJSON.h"
#include <stdlib.h>
#include <string.h>

/**
 * 得到一个十六进制字符对应的字符的十进制ASCII码
 * '0'-'9' -> 0-9
 * 'a'-'f' -> 10-15
 * 'A'-'F' -> 10-15
 */
static int hex_to_char(char hex)
{
    if (hex >= '0' && hex <= '9')
    {
        return hex - '0';
    }
    else if (hex >= 'a' && hex <= 'f')
    {
        return hex -'a' + 10;
    }
    else if (hex >= 'A' && hex <= 'F')
    {
        return hex -'A' + 10;
    }
}

/**
 * 将十六进制字符串转换为对应的字符串
 *   "61626364" -> "abcd"
 */
static char *hex_to_str(char *hex_str, int *str_len)
{
    // 十进制字符串的长度
    int hex_len = strlen(hex_str);
    if(hex_len % 2 != 0)
    {
        log_error("hex_str len error");
        return NULL;
    }
    //  得到对应的字符串的长度，并保存到str_len
    *str_len = hex_len / 2;

    // 分配存储对应字符串的空间
    char *str = (char *)malloc(*str_len + 1);

    // 遍历hex_str, 将每二位的字符转换为对应的字符串  "616263"
    for(int i=0;i<hex_len-1;i=i+2)
    {
        // int high_val = hex_to_char(hex_str[i]);
        // int low_val =  hex_to_char(hex_str[i+1]);
        // str[i/2] = (high_val << 4) | low_val;

        sscanf(&hex_str[i], "%02X", (unsigned int *)&str[i/2]);
    }

    // 在str中添加结束符‘\0'
    str[*str_len] = '\0';

    return str;
}

/**
 * 将字符串转换为十六进制字符串
 */
static char *str_to_hex(char *str, int str_len)
{
    // 分配要生成的十六进制字符串的空间
    char *hex_str = (char *)malloc(str_len * 2 + 1);

    // 遍历字符串str,  将每个字符的十六进制字符添加到hex_str中
    for(int i=0;i<str_len;i++)
    {
        sprintf(hex_str + i * 2, "%02X", str[i]);
    }

    // 向hex_str添加结束符
    hex_str[str_len * 2] = '\0';

    return hex_str;
}

Message *app_message_initByBinary(char *binary, int len)
{
    Message *message = (Message *)malloc(sizeof(Message));

    memset(message, 0, sizeof(Message));
    /*
    二进制数据的格式：
    byte1: conn_type
    byte2: id_len
    byte3: msg_len
    byte4-(id_len+msg_len): id+msg
    */
    // 拷贝conn_type
    memcpy(&message->conn_type, binary, 1);
    // 拷贝id_len
    memcpy(&message->id_len, binary+1, 1);
    // 拷贝msg_len
    memcpy(&message->msg_len, binary+2, 1);
    // 检查len
    if (len != 3 + message->id_len + message->msg_len)
    {
        log_error("binary len error");
        free(message);
        return NULL;
    }
    // 拷贝payload
    message->payload = (char *)malloc(message->id_len + message->msg_len);
    memcpy(message->payload, binary+3, message->id_len + message->msg_len);

    return message;
}

Message *app_message_initByJson(char *json)
{
    // 初始化message空间
    Message *message = (Message *)malloc(sizeof(Message));
    memset(message, 0, sizeof(Message));
    
    // 解析json得到conn_type id_hex msg_hex
    cJSON *root = cJSON_Parse(json);
    if (root == NULL)
    {
        log_error("json parse error");
        free(message);
        return NULL;
    }
    cJSON *type_Obj = cJSON_GetObjectItem(root, "conn_type");
    cJSON *id_Obj = cJSON_GetObjectItem(root, "id");
    cJSON *msg_Obj = cJSON_GetObjectItem(root, "msg");
    if (type_Obj == NULL || id_Obj == NULL || msg_Obj == NULL)
    {
        log_error("json中没有conn_type或id或msg");
        free(message);
        return NULL;
    }
    int conn_type = type_Obj->valueint;
    char *id_hex = id_Obj->valuestring;
    char *msg_hex = msg_Obj->valuestring;

    // 将conn_type给message->conn_type
    message->conn_type = conn_type;

    // 将id_hex和msg_hex转换为id和msg
    // 将id的长度给message->id_len
    // 将msg的长度给message->msg_len
    char *id = hex_to_str(id_hex, &message->id_len);
    char *msg = hex_to_str(msg_hex, &message->msg_len);
    
    // 将id和msg给message->payload
    message->payload = (char *)malloc(message->id_len + message->msg_len);
    memcpy(message->payload, id, message->id_len);
    memcpy(message->payload+message->id_len, msg, message->msg_len);

    // 释放json对象
    cJSON_Delete(root);
    // 释放id和msg
    free(id);
    free(msg);

    log_debug("message init success conn_type:%d, id_len:%d, msg_len:%d,payload:%s",
              message->conn_type, message->id_len, message->msg_len, message->payload);

    return message;
}


int app_message_toBinary(Message *message, char *binary, int len)
{
    /*
    二进制数据的格式：
    byte1: conn_type
    byte2: id_len
    byte3: msg_len
    byte4-(id_len+msg_len): id+msg
    */
   // 检查len
   if (len < 3 + message->id_len + message->msg_len)
   {
       log_error("param len error");
       return -1;
   }
   // 将message中的各个属性拷贝到binary中
   memcpy(binary, &message->conn_type, 1);  // 拷贝的是conn_type的低位字节
   memcpy(binary+1, &message->id_len, 1);
   memcpy(binary+2, &message->msg_len, 1);
   memcpy(binary+3, message->payload, message->id_len + message->msg_len);

   return 3 + message->id_len + message->msg_len;
}


int app_message_toJson(Message *message, char *json, int len)
{
    // 创建空json对象
    cJSON *root = cJSON_CreateObject();
    // 将message的conn_type添加到json对象
    cJSON_AddNumberToObject(root, "conn_type", message->conn_type);
    // 从message的payload中提取id和msg
    // char *id = malloc(message->id_len);
    // memcpy(id, message->payload, message->id_len);
    // char *msg = malloc(message->msg_len);
    // memcpy(msg, message->payload+message->id_len, message->msg_len);
    // 将message中payload的id和msg转换为十六进制字符串， 添加到json对象
    char *id_hex = str_to_hex(message->payload, message->id_len);
    cJSON_AddStringToObject(root, "id", id_hex);
    char *msg_hex = str_to_hex(message->payload+message->id_len, message->msg_len);
    cJSON_AddStringToObject(root, "msg", msg_hex);
    // 将json对象转换为字符串
    char *json_str = cJSON_PrintUnformatted(root);
    if (len < strlen(json_str) + 1)
    {
        log_error("param len error");

        return -1;
    }
    // 将json字符串拷贝到json参数中
    strcpy(json, json_str);

    // 释放json对象和json字符串
    cJSON_Delete(root);
    free(json_str);
    // 释放id_hex和msg_hex
    free(id_hex);
    free(msg_hex);

    // 返回json字符串的长度
    return strlen(json);
}


void app_message_free(Message *message)
{
    if (message->payload)
    {
        free(message->payload);
    }
    free(message);
}